package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.PcSlipDetail;
import com.alks.entity.data.entity.PcSlipTemp;
import com.alks.entity.data.entity.SdBomMtl;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.*;
import com.alks.function.data.request.stockdept.pcfactorystockwork.*;
import com.alks.function.data.vo.controller.stockdept.MtlDocumentVo;
import com.alks.function.mapper.common.BackMapper;
import com.alks.function.mapper.pcfactoryquery.FT_QR_PcSlipDetailMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.*;
import com.alks.function.service.stockdept.pcfactorystockquery.IPcOtherMtlInService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.alks.common.utils.beanutils.ArrayUtils.findMiss;
import static com.alks.entity.data.enums.ResultCodeEnum.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ms
 * @since 2023-09-07
 */
@Service
@Slf4j
public class PcOtherMtlInServiceImpl extends ServiceImpl<SD_SQ_PcSlipTempMapper, PcSlipTemp> implements IPcOtherMtlInService {
    @Autowired
    private SD_SQ_PcSlipTempMapper tempMapper;
    @Autowired
    private FT_QR_PcSlipDetailMapper detailMapper;
    @Autowired
    private SD_SQ_PcLotUsageMapper usageMapper;
    @Autowired
    private SD_SQ_SdBomMtlMapper bomMtlMapper;
    @Autowired
    private SD_SQ_SdMaterialMapper materialMapper;
    @Autowired
    private BackMapper backMapper;
    @Autowired
    private SD_SQ_SdFitDetailMapper fitMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private SD_SQ_PcMtlAccMapper accMapper;
    @Autowired
    private SD_SQ_PcMtlAccPartMapper accPartMapper;
    @Autowired
    private SD_SQ_PcMtlAccPackMapper accPackMapper;

    /*为调用准备*/
    private final Map<String, Object> mapperMap = new HashMap<>();

    public PcOtherMtlInServiceImpl() {
        mapperMap.put("SD_SQ_PcMtlAccMapper", accMapper);
        mapperMap.put("SD_SQ_PcMtlAccPartMapper", accPartMapper);
        mapperMap.put("SD_SQ_PcMtlAccPackMapper", accPackMapper);
    }

    @Override
    public ResponseInfo getOtherMtlWaitQuery() {
        /*获取数据*/
        List<PcSlipTemp> temps = lambdaQuery()
                .eq(PcSlipTemp::getSysUser, UserIdThread.get().getUserName())   //只查当前用户
                .eq(PcSlipTemp::getSlipType, "I")
                .orderBy(true, true, PcSlipTemp::getMtlNo).list();
        /*拷贝获取数据*/
        List<OMtlWaitDto> dtos = BeanUtil.copyList(temps, OMtlWaitDto.class);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo getOtherMtlInQuery(OMtlWatiRequest request, String slipType) {
        /*初始化页码*/
        request.setPageNum(request.getPageNum() == null || request.getPageNum() <= 0 ? 1 : request.getPageNum());
        request.setPageSize(request.getPageSize() == null || request.getPageSize() <= 0 ? 10 : request.getPageSize());

        /*获取数据*/
        LambdaQueryWrapper<PcSlipDetail> wrapper = new LambdaQueryWrapper<PcSlipDetail>()
                .like(request.getSlipNo() != null && !request.getSlipNo().isEmpty(), PcSlipDetail::getSlipNo, request.getSlipNo())
                .eq(request.getSlipReason() != null && !request.getSlipReason().isEmpty(), PcSlipDetail::getSlipReason, request.getSlipReason())
                .like(request.getMtlName() != null && !request.getMtlName().isEmpty(), PcSlipDetail::getMtlName, request.getMtlName())
                .like(request.getLotNo() != null && !request.getLotNo().isEmpty(), PcSlipDetail::getLotNo, request.getLotNo())
                .eq(PcSlipDetail::getSysUser, UserIdThread.get().getUserName())     //只查当前用户
                .eq(PcSlipDetail::getSlipType, slipType)
                .ge(request.getSlipDateStart() != null, PcSlipDetail::getSlipDate, request.getSlipDateStart())
                .le(request.getSlipDateEnd() != null, PcSlipDetail::getSlipDate, request.getSlipDateEnd())
                .orderBy(true, true, PcSlipDetail::getItem);
        IPage<PcSlipDetail> page = detailMapper.selectPage(new Page<>(request.getPageNum(), request.getPageSize()), wrapper);
        /*拷贝提取*/
        List<OMtlInDto> dtos = BeanUtil.copyList(page.getRecords(), OMtlInDto.class);
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotal());
        map.put("dtos", dtos);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getComMtlQuery(ComMtlRequest request) {
        /*初始化页码*/
        request.setPageNum(request.getPageNum() == null || request.getPageNum() <= 0 ? 1 : request.getPageNum());
        request.setPageSize(request.getPageSize() == null || request.getPageSize() <= 0 ? 10 : request.getPageSize());
        /*获取材料类型*/
        String mtlType = request.getMtlTypeL();
        if (!(request.getMtlTypeS() == null || request.getMtlTypeS().isEmpty())) {
            mtlType = request.getMtlTypeS();
        } else if (!(request.getMtlTypeM() == null || request.getMtlTypeM().isEmpty())) {
            mtlType = request.getMtlTypeM();
        }
        /*获取数据*/
        LambdaQueryWrapper<SdBomMtl> wrapper = new LambdaQueryWrapper<SdBomMtl>()
                .like(!(mtlType == null || mtlType.isEmpty()), SdBomMtl::getMtlNo, mtlType)
                .like(!(request.getMtlName_1() == null || request.getMtlName_1().isEmpty()), SdBomMtl::getMtlName, request.getMtlName_1())
                .like(!(request.getMtlName_2() == null || request.getMtlName_2().isEmpty()), SdBomMtl::getMtlName, request.getMtlName_2())
                .like(!(request.getMtlName_3() == null || request.getMtlName_3().isEmpty()), SdBomMtl::getMtlName, request.getMtlName_3())
                .like(!(request.getMtlColor() == null || request.getMtlColor().isEmpty()), SdBomMtl::getMtlColor, request.getMtlColor())
                .like(!(request.getMtlUnit() == null || request.getMtlUnit().isEmpty()), SdBomMtl::getMtlUnit, request.getMtlUnit())
                .like(!(request.getMtlSpec() == null || request.getMtlSpec().isEmpty()), SdBomMtl::getMtlSpec, request.getMtlSpec())
                .groupBy(SdBomMtl::getMtlNo)
                .orderBy(true, true, SdBomMtl::getMtlNo);
        IPage<SdBomMtl> page = bomMtlMapper.selectPage(new Page<>(request.getPageNum(), request.getPageSize()), wrapper);
        /*拷贝提取*/
        List<ComMtlDto> dtos = BeanUtil.copyList(page.getRecords(), ComMtlDto.class);
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotal());
        map.put("dtos", dtos);
        return ResponseInfo.ok(map);
    }

    @Override
    @AutoPageAop
    public ResponseInfo getLotMtlQuery(LotMtlRequest request, int slipType) {
        /*获取数据*/
        List<LotMtlDto> dtos = usageMapper.getLotMtlQuery(request, slipType);
        com.github.pagehelper.Page<LotMtlDto> page = (com.github.pagehelper.Page<LotMtlDto>) dtos;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotal());
        map.put("dtos", dtos);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo otherLotSubMtlQuery(OMtlwaitAddRequest request) {
        /*获取数据*/
        List<LotSubMtlDto> dtos = fitMapper.otherLotSubMtlQuery(request);
        return ResponseInfo.ok(dtos);
    }

    @Override
    @AutoPageAop
    public ResponseInfo getLotComMtlQuery(LotComMtlRequest request) {
        /*获取数据*/
        List<LotComMtlDto> dtos = materialMapper.getLotComMtlQuery(request);
        com.github.pagehelper.Page<LotComMtlDto> page = (com.github.pagehelper.Page<LotComMtlDto>) dtos;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotal());
        map.put("dtos", dtos);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo otherMtlWaitStockAdd(OMtlwaitAddRequest request, Integer type) {
        /*判断数据是否存在*/
        LambdaQueryWrapper<PcSlipTemp> wrapper = new LambdaQueryWrapper<PcSlipTemp>()
                .eq(PcSlipTemp::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcSlipTemp::getSysUser, UserIdThread.get().getUserName())
                .eq(PcSlipTemp::getMtlNo, request.getMtlNo())
                .eq(request.getLotNo() != null && !request.getLotNo().isEmpty(), PcSlipTemp::getLotNo, request.getLotNo());
        PcSlipTemp temp = tempMapper.selectOne(wrapper);
        if (temp != null && !BeanUtil.allIsEmpty(temp)) {
            return ResponseInfo.error("该物料编码已存在", DATA_IS_REPEAT.getCode());
        }
        /*初始化固定数据*/
        PcSlipTemp dto = new PcSlipTemp();
        /*获取需要的数据*/
        switch (type) {
            case 1:
                dto = comMtlQuery(request.getMtlNo());
                break;
            case 2:
                dto = lotMtlQuery(request.getLotNo(), request.getSeqNo());
                break;
            case 3:
                dto = lotComMtlQuery(request.getMtlNo());
                break;
        }
        if (dto == null || BeanUtil.allIsEmpty(dto)) {
            log.error("数据不存在:\nmtlNo{}\nlotNo{}\nseqNo{}", request.getMtlNo(), request.getLotNo(), request.getSeqNo());
            return ResponseInfo.error("数据异常", DATA_IS_ERR.getCode());
        }
        dto.setSysUser(UserIdThread.get().getUserName());
        dto.setSysDate(LocalDateTime.now());
        dto.setStockNo("X1");
        dto.setSlipType("I");
        /*数据检测*/
        if (dto.getMtlNo() == null) {
            log.error("没有找到对应数据或数据材料编号异常：\nLOT_NO:{},SEQ_NO:{},MTL_NO:{}", request.getLotNo(), request.getSeqNo(), request.getMtlNo());
            return ResponseInfo.error("存在异常数据，请联系管理员", DATA_NOT_RETURN.getCode());
        }
        /*补充数据*/
        tempMapper.otherMtlWaitStockAdd(dto);
        return ResponseInfo.ok("新增成功");
    }

    private PcSlipTemp lotComMtlQuery(String mtlNo) {
        PcSlipTemp dto = materialMapper.comMtlQuery(mtlNo);
        return dto;
    }


    /*寻找新增用通用材料数据*/
    private PcSlipTemp comMtlQuery(String mtlNo) {
        PcSlipTemp dto = bomMtlMapper.comMtlQuery(mtlNo);
        return dto;
    }


    /*寻找新增用指令材料数据*/
    private PcSlipTemp lotMtlQuery(String lotNo, Integer seqNo) {
        PcSlipTemp dto = usageMapper.lotMtlQuery(lotNo, seqNo);
        return dto;
    }

    @Override
    @Transactional
    public ResponseInfo otherMtlInStockAdd(OMtlInAddRequest request, String slipType) {
        String companyId = UserIdThread.get().getCompanyId();
        String userName = UserIdThread.get().getUserName();
        /*找出需要的数据*/
        List<PcSlipTemp> temps = tempMapper.tempToStkQuery(slipType, companyId, userName);
        /*判断是否有合法数据可以出库*/
        if (temps == null || temps.isEmpty()) {
            log.warn("异常接口：otherMtlInStockAdd\n异常原因：无大于零出库数据");
            return ResponseInfo.error("没有数量大于0的数据", INPUT_ERROR.getCode());
        }
        /*判断基本材料是否建档,库存是否充足*/
        List<PcSlipTemp> tempAccMtls = temps.stream()
                .filter(a -> !a.getMtlNo().startsWith("U") && !a.getMtlNo().startsWith("P"))              //U和L开头为通用材料 在其他库存中
                .collect(Collectors.toList());
        /*检测建档并抛出异常*/
        if (ArrayUtils.isNoEmpyt(tempAccMtls)) {
            Map<String, BigDecimal> accMap = tempAccMtls.stream()
                    .collect(Collectors.toMap(PcSlipTemp::getMtlNo, PcSlipTemp::getQty,BigDecimal::add));
            List<String> accMtlNos = new ArrayList<>(accMap.keySet());
            if ("I".equals(slipType)) {
                accMapper.stkInByMap(accMap, companyId);
                accMapper.recDateUp(accMtlNos, LocalDate.now().atStartOfDay(), companyId);
            }
            /*收集库存判断库存是否充足*/
            if ("O".equals(slipType)) {
                this.StkCheck(tempAccMtls, "SD_SQ_PcMtlAccMapper", companyId);
                accMapper.stkOutByMap(accMap, companyId);
                accMapper.traDateUp(accMtlNos, LocalDate.now().atStartOfDay(), companyId);
            }
        }
        /*其他材料检测*/
        if (tempAccMtls.size() < temps.size()) {
            /*通用材料检测*/
            List<PcSlipTemp> tempPartMtls = temps.stream()
                    .filter(a -> a.getMtlNo().startsWith("U"))
                    .collect(Collectors.toList());
            if (!ArrayUtils.isEmpyt(tempPartMtls)) {
                Map<String, BigDecimal> partMap = tempPartMtls.stream()
                        .collect(Collectors.toMap(PcSlipTemp::getMtlNo, PcSlipTemp::getQty,BigDecimal::add));
                List<String> partMtlNos = new ArrayList<>(partMap.keySet());
                if ("I".equals(slipType)) {
                    accPartMapper.stkInByMap(partMap, companyId);
                    accPartMapper.recDateUp(partMtlNos, LocalDate.now().atStartOfDay(), companyId);
                }
                /*收集库存判断库存是否充足*/
                if ("O".equals(slipType)) {
                    this.StkCheck(tempPartMtls, "SD_SQ_PcMtlAccPartMapper", companyId);
                    /*更新通用材料库存*/
                    accPartMapper.stkOutByMap(partMap, companyId);
                    accPartMapper.traDateUp(partMtlNos, LocalDate.now().atStartOfDay(), companyId);
                }
            }

            /*包材数据检测*/
            List<PcSlipTemp> tempPackMtls = temps.stream()
                    .filter(a -> a.getMtlNo().startsWith("P"))
                    .collect(Collectors.toList());
            if (!ArrayUtils.isEmpyt(tempPackMtls)) {
                Map<String, BigDecimal> packMap = tempPackMtls.stream()
                        .collect(Collectors.toMap(PcSlipTemp::getMtlNo, PcSlipTemp::getQty,BigDecimal::add));
                List<String> packMtlNos = new ArrayList<>(packMap.keySet());
                if (slipType.equals("I")) {
                    accPackMapper.stkInByMap(packMap, companyId);
                    accPackMapper.recDateUp(packMtlNos, LocalDate.now().atStartOfDay(), companyId);
                }
                /*收集库存判断库存是否充足*/
                if (slipType.equals("O")) {
                    this.StkCheck(tempPackMtls, "SD_SQ_PcMtlAccPackMapper", companyId);
                }
                /*更新包材库存*/
                accPackMapper.stkOutByMap(packMap, companyId);
                accPackMapper.traDateUp(packMtlNos, LocalDate.now().atStartOfDay(), companyId);
            }
        }
        /*更新库存*/
        /*初始化需要输入的数据*/
        List<PcSlipDetail> details = BeanUtil.copyList(temps, PcSlipDetail.class);
        LocalDate now = LocalDate.now();
        /*生成订单号*/
        String key = companyId + "Q" + now.format(DateTimeFormatter.ofPattern("yyMM"));
        RedisAtomicInteger ato = new RedisAtomicInteger(key, redisService.getConnectionFactory());
        String value = String.format("%05d", ato.getAndIncrement());
        redisService.setOutTime(key);
        for (PcSlipDetail detail : details) {
            detail.setSysDate(LocalDateTime.now());
            detail.setSysUser(userName);
            detail.setDeptName(request.getDeptName());
            detail.setDeptNo(request.getDeptNo());
            detail.setSlipReason(request.getSlipReason());
            detail.setSlipDate(request.getSlipDate() == null ? LocalDateTime.now() : request.getSlipDate().atStartOfDay());
            detail.setSlipNo(key + value);
        }
        /*更新数据*/
//        for (PcSlipDetail detail : details) {
//        detailMapper.insert(detail);
//        }
        detailMapper.otherMtlInStockAdd(details);
        /*删除暂存数据*/
        LambdaQueryWrapper<PcSlipTemp> tempWrapper = new LambdaQueryWrapper<PcSlipTemp>()
                .eq(PcSlipTemp::getCompanyId,companyId)
                .eq(PcSlipTemp::getSysUser,userName)
                .eq(PcSlipTemp::getSlipType,slipType)
                .isNotNull(PcSlipTemp::getQty)
                .gt(PcSlipTemp::getQty,0);
        tempMapper.delete(tempWrapper);
        return ResponseInfo.ok("入库成功");
    }

    /**
     * 建档检测
     *
     * @param mapperName
     * @param mapperName
     * @throws RuntimeException
     */
    private void DoucmentCheck(List<PcSlipTemp> temps, String mapperName, String companyId) throws RuntimeException {
        /*获取并调用方法获取存在的物料数据*/
        Object mapper = mapperMap.get(mapperName);
        String checkMethodName = "mtlNoDocumentCheck";
        String documentMethodName = "mtlDocumentCreate";
        if (mapper != null) {
            List<String> accMtlNos;
            List<String> tempMtlNos = temps.stream().filter(Objects::nonNull).map(PcSlipTemp::getMtlNo).collect(Collectors.toList());
            try {
                Method method = mapper.getClass().getMethod(checkMethodName);
                accMtlNos = (List<String>) method.invoke(mapper, tempMtlNos, companyId);
                List<String> mtlMiss = findMiss(tempMtlNos, accMtlNos);
                /*找出不包含（未建档）的数据进行建档*/
                if (!ArrayUtils.isEmpyt(mtlMiss)) {
                    List<MtlDocumentVo> documentVos = BeanUtil.copyList(mtlMiss, MtlDocumentVo.class);
                    for (MtlDocumentVo vo : documentVos) {
                        vo.setCompanyId(companyId);
                        vo.setRecDate(LocalDateTime.now());
                    }
                    Method method1 = mapper.getClass().getMethod(documentMethodName);
                    method1.invoke(mapper, documentVos);
                }
            } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException |
                     ClassCastException e) {
                throw MtlCheckException(mapperName, e, checkMethodName,documentMethodName);
            }
        } else throw new RuntimeException(mapper + "不存在");
    }

    /**
     * 库存检测
     *
     * @param mtlTemps
     * @param mapperName
     * @throws RuntimeException
     */
    private void StkCheck(List<PcSlipTemp> mtlTemps, String mapperName, String companyId) throws RuntimeException {
        /*获取并调用方法获取库存数据*/
        Object mapper = mapperMap.get(mapperName);
        String mapperMethodName = "getStkQty";
        if (mapper != null) {
            List<Map<String, Object>> stkQtyList;
            try {
                Method method = mapper.getClass().getMethod(mapperMethodName);
                /*获取库存和物料编码*/
                stkQtyList = (List<Map<String, Object>>) method.invoke(mapper, mtlTemps, companyId);
                /*处理异常*/
            } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException |
                     ClassCastException e) {
                throw MtlCheckException(mapperName,e,mapperMethodName);
            }
            /*处理库存和物料编码的数据*/
            Map<String, BigDecimal> stkQtyMap = stkQtyList.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(a -> (String) a.get("mtlNo"), a -> (BigDecimal) a.get("qty")));
            /*判断库存是否充足*/
            for (PcSlipTemp temp : mtlTemps) {
                if (temp.getQty().compareTo(stkQtyMap.get(temp.getMtlNo())) > 0) {
                    log.warn("异常接口：otherMtlInStockAdd\n异常原因：试图出库库存不足的材料：{}", temp.getMtlNo());
                    throw new RuntimeException("材料" + temp.getMtlNo() + "库存不足");
                }
            }
        } else throw new RuntimeException(mapperName + "不存在");
    }

    /**
     * 反射相关异常处理
     *
     * @param maperName
     * @param mapperMethodName
     * @param e
     * @return
     */
    private RuntimeException MtlCheckException(String maperName,  Exception e,String... mapperMethodName) {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        String CallerMethodName = stackTrace[2].getMethodName();
        StringBuilder methodName = new StringBuilder();
        for (String name : mapperMethodName) {
            if (methodName.toString().isEmpty()){
                methodName = new StringBuilder(name);
            }else {
                methodName.append("或").append(name);
            }
        }
        String message;
        switch (e.getClass().getName()) {
            case "InvocationTargetException":
                message = maperName + "中的方法" + methodName + "存在异常";
                break;
            case "NoSuchMethodException":
                message = maperName + "中没有找到方法" + methodName;
                break;
            case "IllegalAccessException":
                message = "无权访问" + maperName + "中的方法" + methodName;
                break;
            case "ClassCastException":
                message = maperName + "中的方法" + methodName + "输出不为Map<String,Object>导致数据转换异常";
                break;
            default:
                message = null;
                break;
        }
        log.error("错误接口：{}\n错误原因：{}", CallerMethodName, message);
        return new RuntimeException(e);
    }

    @Override
    @Transactional
    public ResponseInfo otherMtlStockDelete(String slipNo, String slipType) {
        if (StringUtil.isBlank(slipNo)){
            return ResponseInfo.error("删除失败，入库单号不能为空", DATA_IS_ERR.getCode());
        }
        String companyId = UserIdThread.get().getCompanyId();
        /*获取要删除的数据*/
        LambdaQueryWrapper<PcSlipDetail> deleteWrapper = new LambdaQueryWrapper<PcSlipDetail>()
                .eq(PcSlipDetail::getCompanyId, companyId)
                .eq(PcSlipDetail::getSlipNo, slipNo)
                .eq(PcSlipDetail::getSlipType, slipType);
        List<PcSlipDetail> details = detailMapper.selectList(deleteWrapper);
        /*判断数据正确性*/
        if (details.isEmpty()) {
            log.error("错误接口：otherMtlStockDelete\n错误原因：表【PC_SLIP_DETAIL】没有找到订单号对应数据：SLIP_NO：{}", slipNo);
            return ResponseInfo.error("删除失败，请联系管理员", DATA_IS_ERR.getCode());
        }
        /*删除数据*/
        detailMapper.delete(deleteWrapper);

        /*回滚库存*/
        // 修正过滤条件：基本材料（不以P或U开头）
        Map<String, BigDecimal> accMap = details.stream()
                .filter(Objects::nonNull)
                .filter(a -> !a.getMtlNo().startsWith("P") && !a.getMtlNo().startsWith("U"))
                .collect(Collectors.toMap(PcSlipDetail::getMtlNo, PcSlipDetail::getQty, BigDecimal::add));
        if (accMap != null && !accMap.isEmpty()) {
            // 直接调用mapper方法，替代MtlBack方法
            if (slipType.equals("I")) {
                accMapper.stkReduceByMap(accMap, companyId);
                List<String> mtlNos = new ArrayList<>(accMap.keySet());
                accMapper.recDateUp(mtlNos, LocalDateTime.now(), companyId);
            } else if (slipType.equals("O")) {
                accMapper.stkAddByMap(accMap, companyId);
                List<String> mtlNos = new ArrayList<>(accMap.keySet());
                accMapper.traDateUp(mtlNos, LocalDateTime.now(), companyId);
            }
        }

        // 修正过滤条件：包材（以P开头）
        Map<String, BigDecimal> partMap = details.stream()
                .filter(Objects::nonNull)
                .filter(a -> a.getMtlNo().startsWith("P"))
                .collect(Collectors.toMap(PcSlipDetail::getMtlNo, PcSlipDetail::getQty, BigDecimal::add));
        if (partMap != null && !partMap.isEmpty()) {
            // 直接调用mapper方法，替代MtlBack方法
            if (slipType.equals("I")) {
                accPartMapper.stkReduceByMap(partMap, companyId);
                List<String> mtlNos = new ArrayList<>(partMap.keySet());
                accPartMapper.recDateUp(mtlNos, LocalDateTime.now(), companyId);
            } else if (slipType.equals("O")) {
                accPartMapper.stkAddByMap(partMap, companyId);
                List<String> mtlNos = new ArrayList<>(partMap.keySet());
                accPartMapper.traDateUp(mtlNos, LocalDateTime.now(), companyId);
            }
        }

        // 修正过滤条件：通用材料（以U开头）
        Map<String, BigDecimal> packMap = details.stream()
                .filter(Objects::nonNull)
                .filter(a -> a.getMtlNo().startsWith("U"))
                .collect(Collectors.toMap(PcSlipDetail::getMtlNo, PcSlipDetail::getQty, BigDecimal::add));
        if (packMap != null && !packMap.isEmpty()) {
            // 直接调用mapper方法，替代MtlBack方法
            if (slipType.equals("I")) {
                accPackMapper.stkReduceByMap(packMap, companyId);
                List<String> mtlNos = new ArrayList<>(packMap.keySet());
                accPackMapper.recDateUp(mtlNos, LocalDateTime.now(), companyId);
            } else if (slipType.equals("O")) {
                accPackMapper.stkAddByMap(packMap, companyId);
                List<String> mtlNos = new ArrayList<>(packMap.keySet());
                accPackMapper.traDateUp(mtlNos, LocalDateTime.now(), companyId);
            }
        }
        return ResponseInfo.ok("删除成功");
    }


    private void MtlBack(String mapperName, Map<String, BigDecimal> accMap, String slipType,String companyId) {
        /*判断出入库，分别处理*/
        Object mapper = mapperMap.get(mapperName);
        String methodName1="noMethod";
        String methodName2="noMethod";
        if (slipType.equals("I")) {
            methodName1 = "stkReduceByMap";
            methodName2 = "recDateUp";
        } else if (slipType.equals("O")) {
            methodName1 = "stkAddByMap";
            methodName2 = "traDateUp";
        }
        /*实现回滚操作*/
        try {
        Method method1 = mapper.getClass().getMethod(methodName1);
        method1.invoke(mapper, accMap, companyId);
        ArrayList<String> mtlNos = new ArrayList<>(accMap.keySet());
        Method method2 = mapper.getClass().getMethod(methodName2);
        method2.invoke(mapper, mtlNos, companyId);
        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException |
                 ClassCastException e) {
            /*异常处理*/
            throw MtlCheckException(mapperName, e, methodName1,methodName2);
        }

    }

    @Override
    public ResponseInfo otherMtlWaitStockUpdate(List<OMtlWatiUpRequest> request, String slipType) {
        /*更新数据*/
        tempMapper.otherMtlWaitStockUpdate(request, slipType);
        return ResponseInfo.ok("更新成功");
    }

    @Override
    public ResponseInfo otherMtlInBack() {
        /*获取数据*/
        List<Map<String, String>> vendors = backMapper.vendorQuery(null);
        List<Map<String, String>> depts = backMapper.deptQuery();
        List<String> slipReason = backMapper.inSlipReasonQuery();
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("vendors", vendors);
        map.put("depts", depts);
        map.put("slipReason", slipReason);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo otherComMtlBack(String mtlType) {
        /*获取数据*/
        List<Map<String, String>> mtlTypeDtos = backMapper.mtlTypeLMSQuery(mtlType);
        return ResponseInfo.ok(mtlTypeDtos);
    }

    @Override
    public ResponseInfo otherLotMtlBack() {
        List<Map<String, String>> mtlType = backMapper.mtlTypeQuery();
        return ResponseInfo.ok(mtlType);
    }

    @Override
    public ResponseInfo otherLotComMtlBack(String mtlType) {
        /*获取数据*/
        List<Map<String, String>> mtlTypeDtos = backMapper.otherLotComMtlBack(mtlType);
        return ResponseInfo.ok(mtlTypeDtos);
    }


}
